﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace huqiang.Collections
{
    public class LockList<T> where T : class
    {
        List<T> buffer=new List<T>();
        public int Count {
            get 
            {
                bool gotLock = false;
                try
                {
                    spin.Enter(ref gotLock);
                    return buffer.Count;
                }
                finally
                {
                    if (gotLock)
                        spin.Exit();
                }
            } }

        SpinLock spin = new SpinLock();
        public T this[int index]
        {
            get
            {
                if (index < 0)
                    return null;
                bool gotLock = false;
                try
                {
                    spin.Enter(ref gotLock);
                    if (index < buffer.Count)
                        return buffer[index];
                    return null;
                }
                finally
                {
                    if (gotLock)
                        spin.Exit();
                }
            }
            set
            {
                if (index < 0)
                    return;
                bool gotLock = false;
                try
                {
                    spin.Enter(ref gotLock);
                    if (index < buffer.Count)
                        buffer[index] = value;
                }
                finally
                {
                    if (gotLock)
                        spin.Exit();
                }
            }
        }
        public LockList()
        {
        }
        public void Add(T item)
        {
            bool gotLock = false;
            try
            {
                spin.Enter(ref gotLock);
                buffer.Add(item);
            }
            finally
            {
                if (gotLock)
                    spin.Exit();
            }
        }
        public void Insert(int index, T item)
        {
            bool gotLock = false;
            try
            {
                spin.Enter(ref gotLock);
                buffer.Insert(index, item);
            }
            finally
            {
                if (gotLock)
                    spin.Exit();
            }
        }
        public void AddRange(T[] arr)
        {
            bool gotLock = false;
            try
            {
                spin.Enter(ref gotLock);
                buffer.AddRange(arr);
            }
            finally
            {
                if (gotLock)
                    spin.Exit();
            }
        }
        public void Remove(T item)
        {
            bool gotLock = false;
            try
            {
                spin.Enter(ref gotLock);
                buffer.Remove(item);
            }
            finally
            {
                if (gotLock)
                    spin.Exit();
            }
        }
        public T RemoveAt(int index)
        {
            bool gotLock = false;
            try
            {
                spin.Enter(ref gotLock);

                if (index >= 0 & index < buffer.Count)
                {
                    T t = buffer[index];
                    buffer.RemoveAt(index);
                    return t;
                }
                else 
                {
                    //throw new Exception("index out of range"); 
                    return null;
                }
            }
            finally
            {
                if (gotLock)
                    spin.Exit();
            }
        }
        public T Find(Func<T, bool> compare)
        {
            T r = null;
            bool gotLock = false;
            try
            {
                spin.Enter(ref gotLock);
                for (int i = 0; i < buffer.Count; i++)
                {
                    if (compare(buffer[i]))
                    {
                        r = buffer[i];
                        break;
                    }
                }
                return r;
            }
            finally
            {
                if (gotLock)
                    spin.Exit();
            }
        }
        public void Execute(Action<T> action)
        {
            bool gotLock = false;
            try
            {
                spin.Enter(ref gotLock);
                for (int i = 0; i < buffer.Count; i++)
                {
                    action(buffer[i]);
                }
            }
            finally
            {
                if (gotLock)
                    spin.Exit();
            }
        }
        public void Clear()
        {
            bool gotLock = false;
            try
            {
                spin.Enter(ref gotLock);
                for (int i = 0; i < buffer.Count; i++)
                {
                    buffer[i] = null;
                }
            }
            finally
            {
                if (gotLock)
                    spin.Exit();
            }
        }
    }
}
